package cluster

import (
	"encoding/json"
	"github.com/samuel/go-zookeeper/zk"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/viper"
	"xc/app/zookeeper"
)

type TaskInfo struct {
	Name      string
	WorkName  string
	WorkerNum int
}

type TaskNode struct {
}

// Task 集群任务
type Task struct {
	Path  string   //zk路径
	data  []byte   //zk数据
	flags int32    //zk标示
	acl   []zk.ACL //zk权限
}

var task *Task

//InitTask 初始化任务
func InitTask() {
	t := new(Task)
	t.initData()
	t.check()

	task = t
}

//initData 初始化数据
func (t *Task) initData() {
	t.Path = zookeeper.GetTaskPath()
	dataJson, _ := json.Marshal(viper.Get("task"))
	t.data = []byte(dataJson)
	t.acl = zk.WorldACL(zk.PermAll)
	t.flags = 0
}

// 检查任务变化
func (t *Task) check() {
	exist, _, err := zookeeper.Connect().Exists(t.Path)
	if err != nil {
		log.Panic("[task]", err)
	}
	if !exist {
		log.Info("[task]任务节点不存在")

		ret, err := zookeeper.Connect().Create(t.Path, t.data, t.flags, t.acl)
		if err != nil {
			log.Panic("[task]任务节点创建失败")
		}
		log.Info("[task]任务节点创建成功:", ret)
	} else {
		log.Info("[task]任务节点已存在")
	}
}

func TaskWatch() {
	task.watch()
}

// watch 监听task信息变化
//
// 仅当事件为内容变化才做出变化响应
func (t *Task) watch() {
	_, _, watchEvent, err := zookeeper.Connect().GetW(t.Path)
	if err != nil {
		panic(err)
	}

	select {
	case nodeEvent := <-watchEvent:
		{
			log.Info("[task]监听到变化的路径:", nodeEvent.Path)
			log.Info("[task]监听到变化的类型:", nodeEvent.Type.String())

			switch nodeEvent.Type {
			case zk.EventNodeDataChanged:
				// 节点工作
				t.doWork()

				// 循环监听
				t.watch()
			case zk.EventNodeDeleted:
				log.Warn("===========    警告️    ===========")
				log.Warn("[task]监听到task被删除", nodeEvent.Path)
				log.Warn("===========    警告️    ===========")
			default:
				log.Info("[task]监听到未知事件", nodeEvent)
			}
		}
	}
}

func (t *Task) doWork() {
	worker.DoWork()
}

// GetTaskList 获取task信息
//
// 返回数据 [{"name":"test01","workName":"test01","workerNum":3},{"name":"test02","workName":"test02","workerNum":2}]
func (t *Task) GetTaskList() []TaskInfo {
	info, _, err := zookeeper.Connect().Get(t.Path)

	if err != nil {
		log.Info("[worker]获取task信息失败")
		return []TaskInfo{}
	}

	taskList := make([]TaskInfo, 1000) //最大支持1000个任务

	err = json.Unmarshal(info, &taskList)
	if err != nil {
		panic(err)
	}
	return taskList
}

// GetFormatTaskList 获取格式化后的task信息
//
// 返回数据 {"test01":"test01","test02":"test02"}
func (t *Task) GetFormatTaskList() map[string]string {
	taskList := t.GetTaskList()

	var newTaskList = make(map[string]string)

	for _, item := range taskList {
		newTaskList[item.Name] = item.WorkName
	}

	return newTaskList
}
